import { Decimal } from 'decimal.js'
import { cloneDeep, isEmpty } from 'lodash-es'

/**
 * 删除对象中的空Key
 * targetObject:目标对象
 */
export const deleteNullObject = (targetObject: any) => {
  const tempObject = cloneDeep(targetObject)
  let key: keyof typeof tempObject
  for (key in tempObject) {
    if (Object.prototype.hasOwnProperty.call(tempObject, key)) {
      if (isNull(tempObject[key])) {
        delete tempObject[key]
      }
    }
  }
  return tempObject
}

/**
 * 过滤出存在于数组中的树状数据
 * filterArray：数组
 * treeData：原始树状数据(树数组)
 * children：树状结构子节点的Key
 * filterKay：用于判断是否存在数组中（filterArray中元素在treeData中对应的key）
 */
export const filterTreeData = (
  filterArray: any[],
  treeData: any[],
  children: string,
  filterKay: string
) => {
  const tempTreeData = cloneDeep(treeData)
  const newTreeData = tempTreeData.filter((item) => {
    if (item[children]) {
      item[children] = filterTreeData(filterArray, item[children], children, filterKay)
      if (!isEmpty(item[children])) return item
    }
    if (filterArray.includes(item[filterKay])) {
      return item
    }
  })
  return newTreeData
}

/**
 * 删除树状数组中的节点
 * filterArray：数组
 * treeData：原始树状数据(树数组)
 * children：树状结构子节点的Key
 * filterKay：用于判断是否存在数组中（filterArray中元素在treeData中对应的key）
 */
export const deleteTreeNode = (
  filterArray: any[],
  treeData: any[],
  children: string,
  filterKay: string
) => {
  const tempTreeData = cloneDeep(treeData)
  const newTreeData = tempTreeData.filter((item) => {
    if (item[children]) {
      item[children] = deleteTreeNode(filterArray, item[children], children, filterKay)
    }
    if (!filterArray.includes(item[filterKay])) {
      return item
    }
  })
  return newTreeData
}

/**
 * 修改数组中的某一个数据
 * childrenNode：子节点
 * treeData：原始数据(可以是元素为树的数组)
 * filterKay：用于判断是否存在的Key（childrenNode与treeData中对应的唯一key）
 * children：树状结构子节点的Key
 */
export const editArrayNode = (
  childrenNode: { [key: string]: any },
  treeData: any[],
  filterKay = 'ID',
  children = 'SubNodes'
) => {
  const tempTreeData = cloneDeep(treeData)
  const newTreeData = tempTreeData.map((item) => {
    if (item[children]) {
      item[children] = editArrayNode(childrenNode, item[children], filterKay, children)
    }
    if (childrenNode[filterKay] === item[filterKay]) {
      item = childrenNode
    }
    return item
  })
  return newTreeData
}

export interface optionType {
  label: string
  value: string | number
}
/**
 * 对象转数组
 * 把一些对象常量传换成下拉列表
 * @param tagObject
 * @returns
 */
export function objecttoarray(tagObject: any, isReverse = false): optionType[] {
  const tempArray: { label: any; value: any }[] = []
  for (const key in tagObject) {
    if (Object.prototype.hasOwnProperty.call(tagObject, key)) {
      tempArray.push({
        label: isReverse ? tagObject[key] : key,
        value: isReverse ? key : tagObject[key]
      })
    }
  }
  return tempArray
}

// 判空
export function isNull(value: any) {
  switch (Object.prototype.toString.call(value)) {
    case '[object String]':
      return value.replace(/(^s*)|(s*$)/g, '').length === 0
    case '[object Null]':
      return !value
    case '[object Undefined]':
      return !value
    case '[object Array]':
      return JSON.stringify(value) === '[]'
    case '[object Set]':
    case '[object Object]':
      return JSON.stringify(value) === '{}'
    case '[object Number]':
      return isNaN(value)
    default:
      console.log('数据类型为:', Object.prototype.toString.call(value), JSON.stringify(value))
      return false
  }
}

// 使用字符串读取对象中的值
export function getRowIdentity(row: { [key: string]: any }, rowKey: string) {
  if (rowKey.indexOf('.') < 0) {
    return row[rowKey]
  }
  const key = rowKey.split('.')
  let current = row
  key.forEach((element) => {
    current = current ? current[element] : current
  })
  return current
}

// 百分比
export function percentageFormat(value: string | number | Decimal, figures = 2) {
  return Decimal.mul(value || 0, 100).toFixed(figures, Decimal.ROUND_DOWN)
}

/**
 * @description: 多维数组转扁平化，只会把子节点的数据层级提升，并不会把父节点和子节点的数据合并
 * @param {any} treeData 树状数据
 * @param {string} childrenKey 子节点key
 * @return {*}
 */
export function treetoarray(
  treeData: any[],
  childrenKey: string,
  callback?: (item: any) => any
): any[] {
  const tempTreeData = cloneDeep(treeData)
  let cacheData: any[] = []
  for (const iterator of tempTreeData) {
    if (callback) {
      cacheData.push(callback(iterator))
    } else {
      cacheData.push(iterator)
    }
    if (iterator[childrenKey]) {
      cacheData = cacheData.concat(treetoarray(iterator[childrenKey], childrenKey))
    }
  }
  return cacheData
}

/**
 * @description: 寻找在树状数据中的某一个节点的数据
 * @param {anyObj} targetValue 用来定位的目标值
 * @param {any} treeData 树状数据
 * @param {*} filterKay 在数状数据中的定位Key
 * @param {*} children 树状数据中子节点对应的Key
 * @return {*}
 */
export function getTreeNode(
  targetValue: any,
  treeData: any[],
  filterKay: string = 'ID',
  children: string = 'SubNodes'
): any {
  const tempTreeData = cloneDeep(treeData)
  let targetNode = {}
  for (const iterator of tempTreeData) {
    if (!isEmpty(iterator[children])) {
      targetNode = getTreeNode(targetValue, iterator[children], filterKay, children)
      if (!isEmpty(targetNode)) {
        return targetNode
      }
    }
    if (iterator[filterKay] == targetValue) {
      return iterator
    }
  }
  return targetNode
}

// 获取弹框最大高度
export function getDialogMaxHeight(height: number = 98) {
  return document.documentElement.clientHeight - height + 'px'
}

/**
 * @description: 树状数据展开，把父级数据分别放入到子数据中，如果遇到相同的字段以子数据中的字段为主
 * @param {any} treeData
 * @param {string} childrenKey
 * @param {Function} callback
 * @return {*}
 */
export function treeFlat(
  treeData: any[],
  childrenKey: string,
  callback?: (item: any) => any
): any[] {
  const tempTreeData = cloneDeep(treeData)
  let cacheData: any[] = []
  for (const iterator of tempTreeData) {
    if (iterator[childrenKey]) {
      const tempArray = treeFlat(iterator[childrenKey], childrenKey).map((item) => {
        return { ...iterator, ...item }
      })
      cacheData = cacheData.concat(tempArray)
    } else {
      cacheData.push(callback ? callback(iterator) : iterator)
    }
  }
  return cacheData
}

export function roundToMaxPlace(num: number) {
  if (typeof num !== 'number') {
    return { error: '参数应该为数字类型' } // 错误处理
  }

  if (num === 0) {
    return 0 // 特殊处理 0
  }

  // 计算有效位数的数量
  const decimalPlaces = Math.floor(Math.log10(Math.abs(num)))

  // 根据最高位的有效数字对数字进行四舍五入
  const factor = Math.pow(10, decimalPlaces)
  const rounded = Math.ceil(num / factor) * factor // 使用Math.ceil以确保是向上舍入

  return rounded
}

/**
 * 处理金额大写
 * @param money
 * @returns
 */
export function numberToChineseMoney(money: number) {
  if (!money || isNaN(money)) return '金额无效'

  const fraction = ['角', '分']
  const digit = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖']
  const unit = [
    ['元', '万', '亿'],
    ['', '拾', '佰', '仟']
  ]
  const head = money < 0 ? '负' : ''
  money = Math.abs(money)

  let s = ''

  for (let i = 0; i < fraction.length; i++) {
    s += (digit[Math.floor(money * 10 * Math.pow(10, i)) % 10] + fraction[i]).replace(/零./, '')
  }

  s = s || '整'
  money = Math.floor(money)

  for (let i = 0; i < unit[0].length && money > 0; i++) {
    let p = ''
    for (let j = 0; j < unit[1].length && money > 0; j++) {
      p = digit[money % 10] + unit[1][j] + p
      money = Math.floor(money / 10)
    }
    s = p.replace(/(零.)*零$/, '').replace(/^$/, '零') + unit[0][i] + s
  }

  return (
    head +
    s
      .replace(/(零.)*零元/, '元')
      .replace(/(零.)+/g, '零')
      .replace(/^整$/, '零元整')
  )
}
